#include "JobScheduler.h"
#include "Logger.h"
#include <algorithm>
#include <iostream>
#include <numeric>
#include <limits>
#include <cmath>
#include <sstream>

// 线程局部存储，用于保存当前线程的名称
thread_local std::string currentThreadName;

// C++11兼容的make_unique实现
template<typename T, typename... Args>
std::unique_ptr<T> make_unique(Args&&... args) {
    return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
}

JobScheduler::JobScheduler() : initialized_(false), shutdown_(false) {
    // 构造函数实现
}

JobScheduler::~JobScheduler() {
    if (initialized_.load() && !shutdown_.load()) {
        shutdown();
    }
}

void JobScheduler::setJobs(const std::vector<std::shared_ptr<JobInterface>>& jobs) {
    if (initialized_.load()) {
        // 如果已经初始化，则不允许修改任务列表
        return;
    }
    jobs_ = jobs;
}

void JobScheduler::setManualStrategy(const std::vector<std::vector<std::string>>& taskGroups) {
    if (initialized_.load()) {
        // 如果已经初始化，则不允许修改策略
        return;
    }
    manualStrategy_ = taskGroups;
}

void JobScheduler::initialize() {
    if (initialized_.load()) {
        // 防止重复初始化
        return;
    }
    
    // 生成调度策略
    generateSchedulingStrategy();
    
    // 输出调度策略方案到日志
    logSchedulingStrategy();
    
    // 创建线程池
    createThreadPool();
    
    initialized_.store(true);
}

void JobScheduler::shutdown() {
    if (!initialized_.load() || shutdown_.load()) {
        // 未初始化或已关闭
        return;
    }
    
    Logger::getInstance().info("开始关闭调度器...");
    
    shutdown_.store(true);
    
    // 通知所有线程停止
    for (auto& threadData : threadPool_) {
        if (threadData) {
            threadData->running.store(false);
        }
    }
    
    // 等待所有线程结束
    for (auto& threadData : threadPool_) {
        if (threadData && threadData->thread.joinable()) {
            std::ostringstream oss;
            oss << "销毁线程 " << threadData->id << " (" << threadData->name << ")";
            Logger::getInstance().info(oss.str());
            threadData->thread.join();
        }
    }
    
    // 清理资源
    threadPool_.clear();
    
    Logger::getInstance().info("调度器已关闭");
    
    initialized_.store(false);
}

std::vector<ThreadStatus> JobScheduler::getThreadStatus() const {
    std::vector<ThreadStatus> statusList;
    
    // 获取每个线程的状态
    for (const auto& threadData : threadPool_) {
        if (threadData) {
            ThreadStatus status;
            status.id = threadData->id;
            status.name = threadData->name;
            status.status = threadData->running.load() ? "运行中" : "已停止";
            status.jobCount = static_cast<int>(threadData->jobs.size());
            status.lastActiveTime = std::chrono::steady_clock::now(); // 简化实现
            statusList.push_back(status);
        }
    }
    
    return statusList;
}

std::vector<JobStats> JobScheduler::getJobStats() const {
    std::lock_guard<std::mutex> lock(statsMutex_);
    std::vector<JobStats> statsList;
    
    for (const auto& pair : jobStats_) {
        JobStats stats;
        stats.jobId = pair.second->jobId;
        stats.executionCount = pair.second->executionCount.load();
        
        if (pair.second->executionCount.load() > 0) {
            stats.averageTimeMs = static_cast<double>(pair.second->totalTimeMs.load()) / 
                                  static_cast<double>(pair.second->executionCount.load());
        } else {
            stats.averageTimeMs = 0.0;
        }
        
        stats.maxTimeMs = pair.second->maxTimeMs.load();
        // 处理最小时间的初始值问题
        long long minTime = pair.second->minTimeMs.load();
        if (minTime == std::numeric_limits<long long>::max()) {
            stats.minTimeMs = 0;
        } else {
            stats.minTimeMs = minTime;
        }
        stats.timeoutCount = pair.second->timeoutCount.load();
        stats.lastExecutionTime = pair.second->lastExecutionTime;
        
        statsList.push_back(stats);
    }
    
    return statsList;
}

void JobScheduler::generateSchedulingStrategy() {
    // 如果有手动策略，则使用手动策略
    if (!manualStrategy_.empty()) {
        // 根据手动策略分组任务
        // 这里需要将任务ID映射到任务对象
        std::map<std::string, std::shared_ptr<JobInterface>> jobMap;
        for (const auto& job : jobs_) {
            jobMap[job->getId()] = job;
        }
        
        // 清空现有线程池数据
        threadPool_.clear();
        
        // 根据手动策略创建线程组
        for (const auto& group : manualStrategy_) {
            auto threadData = make_unique<ThreadData>();
            threadData->id = static_cast<int>(threadPool_.size());
            threadData->name = getThreadName(threadData->id);
            threadData->running.store(true);
            
            // 将任务添加到线程组
            for (const auto& jobId : group) {
                auto it = jobMap.find(jobId);
                if (it != jobMap.end()) {
                    threadData->jobs.push_back(it->second);
                }
            }
            
            threadPool_.push_back(std::move(threadData));
        }
        
        return;
    }
    
    // 自动策略算法
    // 按周期排序任务
    std::vector<std::shared_ptr<JobInterface>> sortedJobs = jobs_;
    std::sort(sortedJobs.begin(), sortedJobs.end(),
              [](const std::shared_ptr<JobInterface>& a, const std::shared_ptr<JobInterface>& b) {
                  return a->getPeriod() < b->getPeriod();
              });
    
    // 清空现有线程池数据
    threadPool_.clear();
    
    // 使用贪心算法分组任务
    for (const auto& job : sortedJobs) {
        bool assigned = false;
        
        // 尝试将任务分配给现有线程
        for (auto& threadData : threadPool_) {
            // 计算当前线程组的总执行时间
            auto totalExecutionTime = std::chrono::milliseconds(0);
            for (const auto& j : threadData->jobs) {
                totalExecutionTime += j->getMaxExecutionTime();
            }
            
            // 如果加上新任务的执行时间不超过任务周期，则可以分配
            if (totalExecutionTime + job->getMaxExecutionTime() <= job->getPeriod()) {
                threadData->jobs.push_back(job);
                assigned = true;
                break;
            }
        }
        
        // 如果无法分配给现有线程，则创建新线程
        if (!assigned) {
            auto threadData = make_unique<ThreadData>();
            threadData->id = static_cast<int>(threadPool_.size());
            threadData->name = getThreadName(threadData->id);
            threadData->running.store(true);
            threadData->jobs.push_back(job);
            threadPool_.push_back(std::move(threadData));
        }
    }
}

void JobScheduler::createThreadPool() {
    // 初始化统计信息
    {
        std::lock_guard<std::mutex> lock(statsMutex_);
        for (const auto& job : jobs_) {
            // 只有当统计信息不存在时才创建
            if (jobStats_.find(job->getId()) == jobStats_.end()) {
                auto stats = make_unique<JobStatistics>();
                stats->jobId = job->getId();
                jobStats_[job->getId()] = std::move(stats);
            }
        }
    }
    
    // 创建线程
    for (auto& threadData : threadPool_) {
        if (threadData && threadData->jobs.size() > 0) {
            threadData->running.store(true);
            std::ostringstream oss;
            oss << "创建线程 " << threadData->id << " (" << threadData->name << ")，负责任务: ";
            for (size_t i = 0; i < threadData->jobs.size(); ++i) {
                if (i > 0) oss << ", ";
                oss << threadData->jobs[i]->getId();
            }
            Logger::getInstance().info(oss.str());
            
            threadData->thread = std::thread(threadWorker, threadData.get(), this);
        }
    }
}

void JobScheduler::threadWorker(ThreadData* threadData, JobScheduler* scheduler) {
    // 设置线程局部存储中的线程名称
    currentThreadName = threadData->name;
    
    // 每个线程维护一个任务下次执行时间表
    std::map<std::shared_ptr<JobInterface>, std::chrono::steady_clock::time_point> nextExecutionTimes;
    
    // 初始化下次执行时间
    auto now = std::chrono::steady_clock::now();
    for (const auto& job : threadData->jobs) {
        nextExecutionTimes[job] = now + job->getPeriod();
    }
    
    while (threadData->running.load() && !scheduler->shutdown_.load()) {
        // 计算最早下次执行时间
        auto nextTime = std::chrono::steady_clock::time_point::max();
        std::shared_ptr<JobInterface> nextJob = nullptr;
        
        for (const auto& pair : nextExecutionTimes) {
            if (pair.second < nextTime) {
                nextTime = pair.second;
                nextJob = pair.first;
            }
        }
        
        // 如果没有任务需要执行，则等待一段时间
        if (nextJob == nullptr) {
            std::this_thread::sleep_for(std::chrono::milliseconds(100));
            continue;
        }
        
        // 计算需要等待的时间
        now = std::chrono::steady_clock::now();
        if (nextTime > now) {
            std::this_thread::sleep_until(nextTime);
            continue;
        }
        
        // 执行任务
        try {
            auto start = std::chrono::steady_clock::now();
            nextJob->execute();
            auto end = std::chrono::steady_clock::now();
            
            // 计算执行时间
            auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(end - start);
            
            // 检查是否超时
            bool timeout = duration > nextJob->getMaxExecutionTime();
            
            // 更新统计信息
            scheduler->updateJobStats(nextJob->getId(), duration.count(), timeout);
            
            // 更新下次执行时间
            nextExecutionTimes[nextJob] = end + nextJob->getPeriod();
        } catch (const std::exception& e) {
            // 记录异常日志
            std::ostringstream oss;
            oss << "任务 " << nextJob->getId() << " 执行异常: " << e.what();
            Logger::getInstance().error(oss.str());
            
            // 更新下次执行时间（即使出错也继续调度）
            nextExecutionTimes[nextJob] = std::chrono::steady_clock::now() + nextJob->getPeriod();
        }
    }
}

void JobScheduler::updateJobStats(const std::string& jobId, long long executionTimeMs, bool timeout) {
    std::lock_guard<std::mutex> lock(statsMutex_);
    
    auto it = jobStats_.find(jobId);
    if (it != jobStats_.end()) {
        auto& stats = it->second;
        stats->executionCount.fetch_add(1);
        stats->totalTimeMs.fetch_add(executionTimeMs);
        stats->lastExecutionTime = std::chrono::steady_clock::now();
        
        // 更新最大执行时间
        long long currentMax = stats->maxTimeMs.load();
        while (executionTimeMs > currentMax && 
               !stats->maxTimeMs.compare_exchange_weak(currentMax, executionTimeMs)) {}
        
        // 更新最小执行时间
        long long currentMin = stats->minTimeMs.load();
        while (executionTimeMs < currentMin && 
               !stats->minTimeMs.compare_exchange_weak(currentMin, executionTimeMs)) {}
        
        // 更新超时计数
        if (timeout) {
            stats->timeoutCount.fetch_add(1);
            // 记录超时日志
            std::ostringstream oss;
            oss << "任务 " << jobId << " 执行超时: " << executionTimeMs << "ms";
            Logger::getInstance().warning(oss.str());
        }
    }
}

void JobScheduler::logSchedulingStrategy() {
    Logger& logger = Logger::getInstance();
    
    std::ostringstream oss;
    oss << "调度策略方案:";
    
    if (!manualStrategy_.empty()) {
        oss << " 使用手动策略";
    } else {
        oss << " 使用自动策略";
    }
    
    logger.info(oss.str());
    
    for (size_t i = 0; i < threadPool_.size(); ++i) {
        std::ostringstream threadOss;
        threadOss << "线程 " << i << " (" << threadPool_[i]->name << ") 负责任务: ";
        for (size_t j = 0; j < threadPool_[i]->jobs.size(); ++j) {
            if (j > 0) threadOss << ", ";
            threadOss << threadPool_[i]->jobs[j]->getId();
        }
        logger.info(threadOss.str());
    }
}

std::string JobScheduler::getThreadName(int threadId) const {
    std::ostringstream oss;
    oss << "ThreadPool-" << threadId;
    return oss.str();
}